home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_0_m.arj / CHAIN.ASM < prev    next >
Assembly Source File  |  1989-05-28  |  25KB  |  591 lines

  1. PAGE ,132
  2. TITLE File Chain Program, Version 2.16, 24-Dec-1986
  3.  
  4. ; Bug Fix  Version 2.17, 28 May 1989 by David Gwillim
  5. ; Subdirectories were reported as using 0 clusters with 100% waste
  6. ; Also corrected typo for pgm lines storing file size to SIZEMSB
  7. ; Changed/Added lines marked with a comment starting with ;!!
  8. ;
  9. ; Written By Steven Georgiades
  10. ;
  11. ; File Chain Program
  12. ;   Will respond with a list of the disk clusters that make up the file chain
  13. ;   for the requested file.
  14. ;
  15. ;       If you are using this program and find it of value, your
  16. ;       contribution in any amount ($5.00 suggested) will be greatly
  17. ;       appreciated.  Makes checks payable to Steven M. Georgiades.
  18. ;               Thank you.
  19. ;
  20. ;       If you have any questions or comments about this or any other
  21. ;       SMG program, call or write:
  22. ;
  23. ;               Steven M. Georgiades
  24. ;               701-H South Hayward Street
  25. ;               Anaheim, CA 92804
  26. ;               (714) 826-9549
  27. ;
  28.  
  29. CODE      SEGMENT BYTE PUBLIC 'CODE'
  30.  
  31.           ASSUME  CS:CODE,DS:CODE,ES:CODE,SS:CODE
  32.  
  33.           ORG     5CH
  34.  
  35. FCB       LABEL   BYTE
  36.  
  37.           ORG     80H
  38.  
  39. PARAM     LABEL   BYTE
  40.  
  41.           ORG     100H
  42.  
  43. CHAIN:    JMP     BEGIN
  44.  
  45. CHAINMSG1 DB      "The Chain for $"
  46. CHAINMSG2 DB      " is:",13,10,10,"$"
  47. CHAINMSG3 DB      13,10,10
  48. CHAINMSG4 DB      "Total Clusters in File =  XXXXX",13,10,10
  49. CHAINMSG5 DB      "Physical File Length = XXXXXXXX",13,10,"$" ;!!
  50. CHAINMSG6 DB      "Logical  File Length = XXXXXXXX ("
  51. PERCENT   DB      " 0.00% Waste)",13,10,"$"
  52. ISDIR     DB      'File is a SUBDIRECTORY',13,10,"$"       ;!!
  53.  
  54. LOGSZMSG  DW      OFFSET CHAINMSG6
  55.  
  56. CLSTSTR   DB      "XXXXX$"
  57. PRCNT100  DB      "100.0"
  58.  
  59. ANDSTR    DB      " , $"
  60. THRUSTR   DB      " to$"
  61.  
  62. SPECERR   DB      "Invalid File or Path Specification",7,": $"
  63. CRLF      DB      13,10,"$"
  64.  
  65. SIGNON    DB      "File Chain Program, Version 2.17",13,10                  ;!!
  66.           DB      "SMG Software",13,10
  67.           DB      "(C) Copyright 1986, 1989 Steven M. Georgiades"    ;!!
  68.           DB      13,10,13,10,"$"                                    ;!!
  69.  
  70. USAGE     DB      13,10,"Usage:",13,10,13,10                              ;!!
  71.           DB      "  CHAIN [d:][path]filename[.ext]",13,10,13,10          ;!!
  72.           DB      "    Will respond with a list of the disk clusters that make up the specified",13,10
  73.           DB      "    file.  Note that wildcards are NOT allowed.",13,10,"$"
  74.  
  75. CLSTSEC   DW      ?
  76. DIR_LEN   DW      ?
  77. DIRBUF    DW      ?
  78. DIRSEC    DW      ?
  79. DRIVE     DB      ?
  80. EOF       DW      0FF8H
  81. FATSEC    DW      ?
  82. FATSIZE   DB      3
  83. FILENAME  DB      13 DUP(0)
  84. PREV      DW      ?
  85. RANGE     DB      0
  86. SECSIZE   DW      ?
  87. SIZLSB    DW      ?
  88. SIZMSB    DW      ?
  89. STARTSEC  DW      ?
  90.  
  91. FILESPEC  DB      "$",79 DUP(0)
  92.  
  93. BEGIN:    MOV     AH,9                          ; Output Sign-On Message
  94.           MOV     DX,OFFSET SIGNON
  95.           INT     21H
  96.           MOV     AH,19H                        ; Get Default Drive
  97.           INT     21H
  98.           MOV     DRIVE,AL                      ;   and Save
  99.           MOV     SI,OFFSET PARAM               ; Set up Pointer to Parameter
  100.           LODSB                                 ; Read Parameter Length
  101.           CBW
  102.           MOV     BX,AX
  103.           MOV     BYTE PTR [SI][BX],0           ; Terminate Parameter String
  104. STRIP:    LODSB                                 ; Strip Off Leading Whitespace
  105.           CMP     AL,' '
  106.           JE      STRIP
  107.           CMP     AL,9
  108.           JE      STRIP
  109.           OR      AL,AL                         ; If End-of-Parameter, Error
  110.           JNZ     NO_ERR1
  111.           MOV     DX,OFFSET USAGE
  112.           JMP     ERROUT
  113. NO_ERR1:  DEC     SI                            ; ReUse Last Character
  114.           MOV     DI,OFFSET FILESPEC            ; Point to FileSpec Buffer
  115.           CMP     BYTE PTR [SI+1],':'           ; If 2nd Character is Colon,
  116.           JNE     GET_PATH
  117.           AND     AL,0DFH
  118.           SUB     AL,'A'                        ;   Get Drive Number
  119.           MOV     DRIVE,AL
  120.           ADD     SI,2                          ;   and Scan Past
  121. GET_PATH: MOV     AL,DRIVE                      ; Get Drive Number
  122.           ADD     AL,'A'                        ; Convert to Drive Number 
  123.           STOSB                                 ;   in FileSpec
  124.           MOV     AL,':'                        ; Add Colon to FileSpec
  125.           STOSB
  126.           CMP     BYTE PTR [SI],'\'             ; If Next Character is not '\',
  127.           JE      COPYPATH
  128.           MOV     AL,'\'
  129.           STOSB
  130.           PUSH    SI                            ;   Get Current Path to FileSpec
  131.           MOV     SI,DI
  132.           MOV     AH,47H
  133.           MOV     DL,DRIVE
  134.           INC     DL
  135.           INT     21H
  136.           POP     SI
  137.           MOV     AL,0                          ;   Find End-of-FileSpec
  138.           MOV     CX,64
  139.           REPNE   SCASB
  140.           JE      NO_ERR2
  141.           JMP     ERROR
  142. NO_ERR2:  DEC     DI
  143.           CMP     BYTE PTR [DI-1],'\'           ;   If Root DIR, Skip
  144.           JE      COPYPATH
  145.           MOV     AL,'\'                        ;   End-of-FileSpec = '\'
  146.           STOSB
  147. COPYPATH: LODSB                                 ; Copy Rest of Parameter
  148.           OR      AL,AL                         ;   to FileSpec
  149.           JZ      COPYDONE
  150.           STOSB
  151.           JMP     SHORT COPYPATH
  152. COPYDONE: MOV     AL,'$'                        ; Set End-of-FileSpec
  153.           STOSB
  154.           MOV     DX,OFFSET FILESPEC            ; Convert to Upper Case
  155.           CALL    UPPER
  156.           MOV     AL,DRIVE                      ; Read Boot Record
  157.           MOV     CX,1
  158.           MOV     DX,0
  159.           MOV     BX,OFFSET FATBUF
  160.           INT     25H
  161.           POPF
  162.           MOV     AX,FATBUF[11]                 ; Read Sector Size
  163.           MOV     SECSIZE,AX                    ;   and Save
  164.           MOV     AL,BYTE PTR FATBUF[13]        ; Read Sectors per Cluster
  165.           XOR     AH,AH
  166.           MOV     CLSTSEC,AX                    ;   and Save
  167.           MOV     CX,FATBUF[14]                 ; Read # of Reserved Sectors
  168.           MOV     AL,BYTE PTR FATBUF[16]        ; Read # of FAT's
  169.           XOR     AH,AH                         ; Convert to Word
  170.           MOV     BX,FATBUF[22]                 ; Read Sectors per FAT
  171.           MOV     FATSEC,BX
  172.           MUL     BX                            ; Calculate Total FAT Sectors
  173.           ADD     CX,AX                         ; Add to Reserved Sectors
  174.           MOV     AX,FATBUF[17]                 ; Read Number of DIR Entries
  175.           MOV     DIR_LEN,AX
  176.           PUSH    CX                            ; Calculate DIR Sectors
  177.           MOV     CL,5
  178.           SHL     AX,CL
  179.           POP     CX
  180.           MOV     BX,SECSIZE
  181.           XOR     DX,DX
  182.           DIV     BX
  183.           OR      DX,DX                         ; Adjust for Partial Sector
  184.           JZ      NO_ADD
  185.           INC     AX
  186. NO_ADD:   MOV     DIRSEC,AX                     ; Save DIR Sectors
  187.           ADD     CX,AX                         ; Add DIR Sectors to Reserved
  188.           MOV     STARTSEC,CX                   ; Save in STARTSEC
  189.           MOV     AX,FATSEC                     ; Calculate FAT Buffer Size
  190.           MOV     BX,SECSIZE
  191.           MUL     BX
  192.           MOV     BX,AX
  193.           LEA     AX,FATBUF[BX]                 ; Get DIR Buffer Pointer
  194.           MOV     DIRBUF,AX
  195.           MOV     AX,FATBUF[19]                 ; Read Total Sectors on Media
  196.           SUB     AX,CX                         ; Calculate Total Data Clusters
  197.           MOV     BX,CLSTSEC
  198.           XOR     DX,DX
  199.           DIV     BX
  200.           CMP     AX,4079                       ; If Necessary, Adjust FAT Size
  201.           JLE     FAT_OK
  202.           MOV     FATSIZE,4
  203.           MOV     EOF,0FFF8H
  204. FAT_OK:   MOV     AL,DRIVE                      ; Read FAT
  205.           MOV     CX,FATSEC
  206.           MOV     DX,1
  207.           MOV     BX,OFFSET FATBUF
  208.           INT     25H
  209.           POPF
  210.           MOV     AL,DRIVE                      ; Read Root Directory
  211.           MOV     CX,DIRSEC
  212.           MOV     DX,STARTSEC
  213.           SUB     DX,CX
  214.           MOV     BX,DIRBUF
  215.           INT     25H
  216.           POPF
  217.           MOV     SI,OFFSET FILESPEC[3]         ; Point to First Element of Path
  218. NEXT_FLD: MOV     DI,OFFSET FILENAME            ; Point to FileName Buffer
  219. NEXTCHAR: LODSB                                 ; Copy Path Element to FileName
  220.           CMP     AL,'\'                        ;   until '\' or '$'
  221.           JE      GOT_DIR
  222.           CMP     AL,'$'
  223.           JE      GOT_FNM
  224.           STOSB
  225.           JMP     SHORT NEXTCHAR
  226. GOT_DIR:  MOV     AL,0                          ; If '\', Read Subdirectory
  227.           STOSB
  228.           CALL    READDIR
  229.           JNC     NEXT_FLD                      ;   If No Error, Get Next Dir
  230.           JMP     ERROR                         ;   Else Flag Error
  231. GOT_FNM:  MOV     AL,0                          ; If '$',
  232.           STOSB
  233.           CALL    SRCHFILE                      ;   Read File DIR Info
  234.           JNC     NO_ERR3
  235.           JMP     ERROR                         ; If Error, Say So
  236. NO_ERR3:  MOV     AX,[BX+28]                    ; Read File Length
  237.           MOV     SIZLSB,AX
  238.           MOV     DX,[BX+30]
  239.           MOV     SIZMSB,DX                     ;!! was mov sizmsb,ax
  240.           MOV     DI,OFFSET CHAINMSG6[31]       ; Convert to ASCII
  241.           CALL    DEC8OUT                       ; Strip Off Leading Zeroes
  242.           CALL    STRIP0
  243.           MOV     AH,9                          ; Output FileSpec Message
  244.           MOV     DX,OFFSET CHAINMSG1
  245.           INT     21H
  246.           MOV     AH,9
  247.           MOV     DX,OFFSET FILESPEC
  248.           INT     21H
  249.           MOV     AH,9
  250.           MOV     DX,OFFSET CHAINMSG2
  251.           INT     21H
  252.           MOV     BX,[BX+26]                    ; Read Starting Cluster Number
  253.           XOR     CX,CX                         ; Cluster Count = 0
  254.           OR      BX,BX                         ; If Start Cluster = 0, Done
  255.           JZ      LASTCLST
  256.           MOV     AX,BX                         ; Output First Cluster Number
  257.           CALL    OUT_CLST
  258.           MOV     PREV,BX                       ; Previous Cluster = First
  259.           INC     CX                            ; Cluster Count = 1
  260.           CALL    NEXTCLST                      ; Get Next Cluster Number
  261.           CMP     BX,EOF                        ; If Last, Skip
  262.           JNB     LASTCLST
  263. CLSTLOOP: INC     CX                            ; Increment Cluster Count
  264.           MOV     AX,PREV                       ; If Cluster is Previous + 1,
  265.           INC     AX
  266.           CMP     AX,BX
  267.           JNE     CLSTOUT
  268.           MOV     RANGE,-1                      ;   Set Range Flag
  269.           JMP     SHORT NEXTONE
  270. CLSTOUT:  CMP     RANGE,0                       ; Else
  271.           JE      NORANGE                       ;   If Range Flag is Set, 
  272.           MOV     AH,9                          ;     Output " - "
  273.           MOV     DX,OFFSET THRUSTR
  274.           INT     21H
  275.           MOV     AX,PREV                       ;     Output Last Clstr in Range
  276.           CALL    OUT_CLST
  277.           MOV     RANGE,0                       ;     Reset Range Flag
  278. NORANGE:  MOV     AH,9                          ;   Output ",  "
  279.           MOV     DX,OFFSET ANDSTR
  280.           INT     21H
  281.           MOV     AX,BX                         ; Output Cluster Number
  282.           CALL    OUT_CLST
  283. NEXTONE:  MOV     PREV,BX                       ; Previous = Current
  284.           CALL    NEXTCLST                      ; Get Next Cluster Number
  285.           CMP     BX,EOF                        ; If Not EOF, Repeat
  286.           JB      CLSTLOOP
  287.           CMP     RANGE,0                       ; If Range Flag is Set,
  288.           JE      LASTCLST
  289.           MOV     AH,2                          ;   Output " - "
  290.           MOV     DL,'-'
  291.           INT     21H
  292.           MOV     AX,PREV                       ;   Output Last Cluster of Range
  293.           CALL    OUT_CLST
  294. LASTCLST: MOV     AX,SIZMSB                     ; If Size = 0, 100% Waste
  295.           OR      AX,SIZLSB
  296.           JNZ     NOT_ZERO
  297.           JCXZ    LC1                           ;!! allow for <DIR> files
  298.           MOV     LOGSZMSG,OFFSET ISDIR         ;!! say this is a subdirectory
  299.           JMP     SHORT CLSTCNT                 ;!!
  300. LC1:      MOV     SI,OFFSET PRCNT100
  301.           MOV     DI,OFFSET PERCENT
  302.           MOV     CX,5
  303.           REP     MOVSB
  304.           JMP     SHORT CLSTCNT
  305. NOT_ZERO: MOV     AX,SECSIZE                    ; Calculate Percent Waste
  306.           MOV     BX,CLSTSEC
  307.           MUL     BX
  308.           MOV     BX,AX
  309.           MUL     CX
  310.           SUB     AX,SIZLSB
  311.           MOV     DX,100
  312.           MUL     DX
  313.           DIV     BX
  314.           PUSH    DX
  315.           XOR     DX,DX
  316.           DIV     CX
  317.           PUSH    DX
  318.           MOV     DI,OFFSET PERCENT[2]          ; Convert Percent to ASCII
  319.           CALL    DEC2OUT
  320.           CALL    STRIP0
  321.           POP     AX
  322.           MUL     BX
  323.           POP     DI
  324.           ADD     AX,DI
  325.           ADC     DX,0
  326.           DIV     CX
  327.           MOV     DX,100
  328.           MUL     DX
  329.           DIV     BX
  330.           MOV     DI,OFFSET PERCENT[5]
  331.           CALL    DEC2OUT
  332. CLSTCNT:  MOV     AX,CX                         ; Convert Cluster Count to ASCII
  333.           MOV     DI,OFFSET CHAINMSG4[31]
  334.           CALL    DEC5OUT
  335.           CALL    STRIP0                        ; Strip Off Leading Zeroes
  336.           MOV     AX,CLSTSEC                    ; Calculate Physical File Size
  337.           MUL     CX
  338.           MOV     CX,SECSIZE
  339.           MUL     CX
  340.           MOV     DI,OFFSET CHAINMSG5[31]       ; Convert to ASCII
  341.           CALL    DEC8OUT
  342.           CALL    STRIP0                        ; Strip Off Leading Zeroes
  343.           MOV     AH,9                          ; Output Trailer Message
  344.           MOV     DX,OFFSET CHAINMSG3
  345.           INT     21H
  346.           MOV     AH,9                          ;!! Output Logical Size message
  347.           MOV     DX,LOGSZMSG                   ;!!
  348.           INT     21H                           ;!!
  349.           MOV     AX,4C00H                      ; Exit to DOS
  350.           INT     21H
  351. ERROR:    MOV     AH,9                          ; Output Error Message
  352.           MOV     DX,OFFSET SPECERR
  353.           INT     21H
  354.           MOV     AH,9
  355.           MOV     DX,OFFSET FILESPEC            ; Output FileSpec
  356.           INT     21H
  357.           MOV     DX,OFFSET CRLF
  358. ERROUT:   MOV     AH,9
  359.           INT     21H
  360.           MOV     AX,4C01H                      ; Exit to DOS
  361.           INT     21H
  362.  
  363. SRCHFILE: PUSH    AX                            ; Save Register
  364.           PUSH    CX
  365.           PUSH    DI
  366.           PUSH    SI
  367.           CMP     FILENAME,'.'                  ; If Filename Starts with '.',
  368.           JNE     SRCHFIL2
  369.           MOV     SI,OFFSET FILENAME            ;   Copy Filename to FCB
  370.           MOV     DI,OFFSET FCB[1]
  371.           MOV     CX,11
  372. SRCHFIL1: LODSB
  373.           STOSB
  374.           OR      AL,AL
  375.           LOOPNZ  SRCHFIL1
  376.           INC     CX                            ;   and Pad With Spaces
  377.           DEC     DI
  378.           MOV     AL,' '
  379.           REP     STOSB
  380.           JMP     SHORT SRCHFIL3
  381. SRCHFIL2: MOV     AX,2900H                      ; Else Parse Filename
  382.           MOV     SI,OFFSET FILENAME
  383.           MOV     DI,OFFSET FCB
  384.           INT     21H
  385. SRCHFIL3: MOV     DI,OFFSET FCB[1]              ; Point to Filename in FCB
  386.           MOV     SI,DIRBUF                     ; Point to Start of DIRBUF
  387.           MOV     CX,DIR_LEN                    ; Load DIR Length
  388.           JCXZ    SRCHFIL5                      ; If Zero, Not Found
  389. SRCHFIL4: PUSH    CX                            ; Save Registers
  390.           PUSH    DI
  391.           PUSH    SI
  392.           MOV     CX,11                         ; Compare Filename
  393.           REPE    CMPSB
  394.           POP     SI                            ; Restore Registers
  395.           POP     DI
  396.           POP     CX
  397.           JE      SRCHFIL6                      ; If Match, Found
  398.           ADD     SI,32                         ; Else Next DIR Entry
  399.           LOOP    SRCHFIL4                      ; and Repeat
  400. SRCHFIL5: STC                                   ; Set Error Flag
  401.           JMP     SHORT SRCHFIL7                ; Done
  402. SRCHFIL6: MOV     BX,SI                         ; Set Pointer to DIR Entry
  403.           CLC                                   ; Clear Error Flag
  404. SRCHFIL7: POP     SI                            ; Restore Registers
  405.           POP     DI
  406.           POP     CX
  407.           POP     AX
  408.           RET                                   ; Done
  409.  
  410. READDIR:  PUSH    CX                            ; Save Registers
  411.           PUSH    DI
  412.           PUSH    SI
  413.           CALL    SRCHFILE                      ; Search for DIR
  414.           JC      READDIR2                      ; If Not Found, Error
  415.           MOV     BX,[BX+26]                    ; Get Starting Cluster Number
  416.           MOV     DIR_LEN,0                     ; DIR Length = 0
  417.           OR      BX,BX                         ; If Start Cluster = 0, Error
  418.           JZ      READDIR2
  419.           MOV     AX,SECSIZE                    ; Calculate DIR Entries/Cluster
  420.           MOV     CX,CLSTSEC
  421.           MUL     CX
  422.           MOV     CL,5
  423.           SHR     AX,CL
  424.           MOV     CX,AX
  425.           MOV     DI,DIRBUF                     ; Point to DIR Buffer
  426. READDIR1: CALL    READCLST                      ; Read Cluster
  427.           ADD     DIR_LEN,CX                    ; Increment DIR Length
  428.           CMP     BX,EOF                        ; If Not Last Cluster,
  429.           JB      READDIR1                      ;   Get Next Cluster
  430.           JMP     SHORT READDIR3                ; Done Reading DIR
  431. READDIR2: STC                                   ; Set Error Flag
  432. READDIR3: POP     SI                            ; Restore Registers
  433.           POP     DI
  434.           POP     CX
  435.           RET                                   ; Done
  436.  
  437. READCLST: PUSH    AX                            ; Save Registers
  438.           PUSH    CX
  439.           PUSH    DX
  440.           MOV     AX,BX                         ; Calculate Absolute Sector #
  441.           SUB     AX,2
  442.           MOV     CX,CLSTSEC
  443.           MUL     CX
  444.           ADD     AX,STARTSEC
  445.           MOV     DX,AX
  446.           MOV     AL,DRIVE
  447.           PUSH    BX                            ; Save Registers
  448.           PUSH    DI
  449.           MOV     BX,DI                         ; Read Cluster
  450.           INT     25H
  451.           POPF
  452.           POP     DI                            ; Restore Registers
  453.           POP     BX
  454.           CALL    NEXTCLST                      ; Get Next Cluster Number
  455.           MOV     AX,CLSTSEC                    ; Increment Buffer Pointer
  456.           MOV     CX,SECSIZE
  457.           MUL     CX
  458.           ADD     DI,AX
  459.           POP     DX                            ; Restore Registers
  460.           POP     CX
  461.           POP     AX
  462.           RET                                   ; Done
  463.  
  464. NEXTCLST: CMP     FATSIZE,3                     ; If FAT Size = 16 Bits,
  465.           JE      NEXTCLS1
  466.           SHL     BX,1                          ;   Simply Read Next Cluster #
  467.           MOV     BX,FATBUF[BX]
  468.           RET                                   ;   Done
  469. NEXTCLS1: PUSH    AX                            ; Save Registers
  470.           PUSH    CX
  471.           MOV     AX,BX                         ; Word # = Cluster # * 1.5
  472.           SHL     AX,1
  473.           ADD     BX,AX
  474.           SHR     BX,1
  475.           MOV     BX,FATBUF[BX]
  476.           JNC     NEXTCLS2                      ; If Odd, Use 12 MSB's
  477.           MOV     CL,4
  478.           SHR     BX,CL
  479. NEXTCLS2: AND     BX,0FFFH                      ; Else Use 12 LSB's
  480.           POP     CX                            ; Restore Registers
  481.           POP     AX
  482.           RET                                   ; Done
  483.  
  484. UPPER:    PUSH    AX                            ; Save Registers
  485.           PUSH    DX
  486.           PUSH    DI
  487.           PUSH    SI
  488.           MOV     SI,DX                         ; Set Up Source Index
  489.           MOV     DI,DX                         ; Set Up Destination Index
  490. UPPER1:   LODSB                                 ; Read From Source
  491.           OR      AL,AL                         ; If EOS, Done
  492.           JZ      UPPER3
  493.           CMP     AL,'a'                        ; If Lower Case,
  494.           JL      UPPER2
  495.           CMP     AL,'z'
  496.           JG      UPPER2
  497.           SUB     AL,'a'-'A'                    ;   Convert to Upper Case
  498. UPPER2:   STOSB                                 ; Save in Destination
  499.           JMP     SHORT UPPER1                  ; Repeat
  500. UPPER3:   POP     SI                            ; Restore Registers
  501.           POP     DI
  502.           POP     DX
  503.           POP     AX
  504.           RET                                   ; Done
  505.  
  506. OUT_CLST: PUSH    AX                            ; Save Registers
  507.           PUSH    DX
  508.           PUSH    DI
  509.           MOV     DI,OFFSET CLSTSTR[5]          ; Convert Cluster # to Decimal
  510.           CALL    DEC5OUT
  511.           CALL    STRIP0                        ; Strip Off Leading Zeroes
  512.           MOV     AH,9                          ; Output Cluster Number
  513.           MOV     DX,OFFSET CLSTSTR
  514.           INT     21H
  515.           POP     DI                            ; Restore Registers
  516.           POP     DX
  517.           POP     AX
  518.           RET                                   ; Done
  519.  
  520. STRIP0:   CMP     BYTE PTR [DI],'0'             ; If Character != '0', Done
  521.           JNE     STRIP1
  522.           CMP     BYTE PTR [DI+1],'0'           ; If Next Character != Digit,
  523.           JL      STRIP1                        ;   Done
  524.           CMP     BYTE PTR [DI+1],'9'
  525.           JG      STRIP1
  526.           MOV     BYTE PTR [DI],' '             ; Change '0' to ' '
  527.           INC     DI                            ; Point to Next Character
  528.           JMP     SHORT STRIP0                  ; Repeat
  529. STRIP1:   RET                                   ; Done
  530.  
  531. DEC2OUT:  PUSH    AX                            ; Save Registers
  532.           PUSH    BX
  533.           XOR     AH,AH                         ; Clear AH
  534.           MOV     BL,10                         ; AH=AX%10,AL=AX/10
  535.           DIV     BL
  536.           ADD     AX,'00'                       ; Convert to ASCII
  537.           SUB     DI,2
  538.           MOV     [DI],AX                       ; Store in String
  539.           POP     BX                            ; Restore Registers
  540.           POP     AX
  541.           RET                                   ; Done
  542.  
  543. DEC4OUT:  PUSH    AX                            ; Save Registers
  544.           PUSH    BX
  545.           MOV     BL,100                        ; AH=AX%100,AL=AX/100
  546.           DIV     BL
  547.           XCHG    AH,AL                         ; Convert 2 LSD's
  548.           CALL    DEC2OUT
  549.           XCHG    AH,AL                         ; Convert 2 MSD's
  550.           CALL    DEC2OUT
  551.           POP     BX                            ; Restore Registers
  552.           POP     AX
  553.           RET                                   ; Done
  554.  
  555. DEC5OUT:  PUSH    AX                            ; Save Registers
  556.           PUSH    BX
  557.           PUSH    DX                            ; DX=AX%10000,AX=AX/10000
  558.           MOV     BX,10000
  559.           XOR     DX,DX
  560.           DIV     BX
  561.           XCHG    DX,AX                         ; Convert 4 LSD's
  562.           CALL    DEC4OUT
  563.           XCHG    DX,AX                         ; Convert MSD
  564.           ADD     AL,'0'
  565.           SUB     DI,1
  566.           MOV     [DI],AL
  567.           POP     DX                            ; Restore Registers
  568.           POP     BX
  569.           POP     AX
  570.           RET                                   ; Done
  571.  
  572. DEC8OUT:  PUSH    AX                            ; Save Registers
  573.           PUSH    BX
  574.           PUSH    DX
  575.           MOV     BX,10000                      ; DX=DX:AX%10000,AX=DX:AX/10000
  576.           DIV     BX
  577.           XCHG    DX,AX                         ; Convert 4 LSD's
  578.           CALL    DEC4OUT
  579.           XCHG    DX,AX                         ; Convert 4 MSD's
  580.           CALL    DEC4OUT
  581.           POP     DX                            ; Restore Registers
  582.           POP     BX
  583.           POP     AX
  584.           RET                                   ; Done
  585.  
  586. FATBUF    LABEL   WORD
  587.  
  588. CODE      ENDS
  589.  
  590.           END     CHAIN
  591.